package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"regexp"
	"sync"
)

var (
	domain    = "https://www.shopify.com"   // 域名
	linkFmt   = "%s/zh/blog/latest?page=%d" // 链接格式
	startPage = 1                           // 开始页
	endPage   = 45                          // 结束页
)

var (
	mp     map[int][]string // 用于保存每页链接
	locker sync.Mutex
	wg     sync.WaitGroup
	ch     chan int
)

func main() {
	fmt.Println("begin...")

	mp = make(map[int][]string)
	ch = make(chan int, 5)

	// 开启多个协程出来
	for i := 0; i < 10; i++ {
		go work(ch)
	}

	for i := startPage; i <= endPage; i++ {
		ch <- i
		wg.Add(1)
	}

	wg.Wait()

	saveToFile()

	fmt.Println("finish...")
}

func work(ch chan int) {
	for {
		select {
		case pageNum := <-ch:
			content, err := getHtmlContent(pageNum)
			if err == nil {
				locker.Lock()
				mp[pageNum] = parseHtml(content)
				locker.Unlock()
			}
			wg.Done()
		}
	}
}

// 获取html内容
func getHtmlContent(pageNum int) (string, error) {
	link := fmt.Sprintf(linkFmt, domain, pageNum)
	resp, err := http.Get(link)
	if err != nil {
		fmt.Println("[http.Get] ", pageNum, err)
		return "", err
	}

	defer resp.Body.Close()

	b, err := io.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("[io.ReadAll] ", pageNum, err)
		return "", err
	}

	return string(b), nil
}

// 解析html
func parseHtml(content string) []string {
	// <a class="tracking-[-.02em] font-normal pb-4 hover:underline font-aktivgroteskextended text-shade-100 text-base" href="/zh/blog/monetizing-your-content" rel="" target="_self">Wait But Why创始人专访：受众变现的正确方式</a>
	// <a class="tracking-[-.02em] font-normal pb-4 hover:underline font-aktivgroteskextended text-shade-100 text-base" href="/zh/blog/business-marketing" rel="" target="_self">商业营销：类型、策略和示例</a>
	re := regexp.MustCompile(`<a class="tracking-\[-.02em\][a-zA-Z0-9\-\.: ]+" href="([a-zA-Z0-9\-/]+)" rel="" target="_self">([^>]+)</a>`)
	result := re.FindAllStringSubmatch(content, -1)

	data := make([]string, 0)
	for _, v := range result {
		item := fmt.Sprintf("[%s](%s)", v[2], fmt.Sprintf("%s%s", domain, v[1]))
		data = append(data, item)
	}

	return data
}

// 保存到文件
func saveToFile() {
	f, err := os.OpenFile("README.md", os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		fmt.Println(err)
		return
	}

	defer f.Close()

	for i := startPage; i <= endPage; i++ {
		for _, v := range mp[i] {
			f.WriteString(v)
			f.WriteString("  \n")
		}
	}
}
